home *** CD-ROM | disk | FTP | other *** search
/ Super PC 33 / Super PC 33 (Shareware).iso / spc / sonido / timidity / source / wav2pat.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-08-03  |  8.2 KB  |  339 lines

  1. /*
  2.  
  3.     Wav2pat -- simple WAVE to GUS patch converter
  4.     Copyright (C) 1995 Tuukka Toivonen <titoivon@snakemail.hut.fi>
  5.  
  6.     This program is free software; you can redistribute it and/or modify
  7.     it under the terms of the GNU General Public License as published by
  8.     the Free Software Foundation; either version 2 of the License, or
  9.     (at your option) any later version.
  10.  
  11.     This program is distributed in the hope that it will be useful,
  12.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.     GNU General Public License for more details.
  15.  
  16.     You should have received a copy of the GNU General Public License
  17.     along with this program; if not, write to the Free Software
  18.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  
  20.     This is a little tool to convert RIFF WAVEs to GUS-compatible
  21.     patches. A WAVE is read from stdin, and a GUS patch is written to
  22.     stdout.
  23.  
  24. */
  25.  
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28. #include <unistd.h>
  29. #include <fcntl.h>
  30. #include <strings.h>
  31. #include "config.h"
  32. #include "instruments.h"
  33.  
  34. #define DEFAULT_NOTE 60
  35. #define DEFAULT_ROOT 261626
  36.  
  37. int32 freq_table[128]=
  38. {
  39.  8176, 8662, 9177, 9723, 
  40.  10301, 10913, 11562, 12250, 
  41.  12978, 13750, 14568, 15434,
  42.  
  43.  16352, 17324, 18354, 19445,
  44.  20602, 21827, 23125, 24500, 
  45.  25957, 27500, 29135, 30868, 
  46.  
  47.  32703, 34648, 36708, 38891,
  48.  41203, 43654, 46249, 48999,
  49.  51913, 55000, 58270, 61735,
  50.  
  51.  65406, 69296, 73416, 77782,
  52.  82407, 87307, 92499, 97999,
  53.  103826, 110000, 116541, 123471,
  54.  
  55.  130813, 138591, 146832, 155563,
  56.  164814, 174614, 184997, 195998,
  57.  207652, 220000, 233082, 246942,
  58.  
  59.  261626, 277183, 293665, 311127,
  60.  329628, 349228, 369994, 391995,
  61.  415305, 440000, 466164, 493883,
  62.  
  63.  523251, 554365, 587330, 622254,
  64.  659255, 698456, 739989, 783991,
  65.  830609, 880000, 932328, 987767,
  66.  
  67.  1046502, 1108731, 1174659, 1244508,
  68.  1318510, 1396913, 1479978, 1567982,
  69.  1661219, 1760000, 1864655, 1975533,
  70.  
  71.  2093005, 2217461, 2349318, 2489016,
  72.  2637020, 2793826, 2959955, 3135963,
  73.  3322438, 3520000, 3729310, 3951066,
  74.  
  75.  4186009, 4434922, 4698636, 4978032,
  76.  5274041, 5587652, 5919911, 6271927,
  77.  6644875, 7040000, 7458620, 7902133,
  78.  
  79.  8372018, 8869844, 9397273, 9956063, 
  80.  10548082, 11175303, 11839822, 12543854
  81. };
  82.  
  83. int main(int argc, char **argv)
  84. {
  85.   int32
  86.     note=DEFAULT_NOTE,
  87.     root=DEFAULT_ROOT,
  88.     verbosity=0,
  89.     samplerate=-1,
  90.     datasize=-1,
  91.     junklength, c;
  92.  
  93.   int
  94.     infd=STDIN_FILENO;
  95.  
  96.   unsigned char 
  97.     thing[4096],
  98.     *point, 
  99.     modes=0;
  100.  
  101.   while ((c=getopt(argc, argv, "r:n:v"))>0)
  102.     switch(c)
  103.       {
  104.       case 'r': root=atol(optarg); break;
  105.       case 'n': root=freq_table[atoi(optarg) & 127]; break;
  106.       case 'u': note=atol(optarg); break;
  107.       case 'v': verbosity++; break;
  108.       default: return 1;
  109.       }
  110.  
  111.   if (optind==argc-1)
  112.     {
  113.       if ((infd=open(argv[optind], O_RDONLY))<0)
  114.     {
  115.       perror("wav2pat: I can't open your WAVE");
  116.       return 3;
  117.     }
  118.     }
  119.   else if (optind!=argc)
  120.     {
  121.       fprintf(stderr, 
  122.           "Usage: wav2pat [-r RootFreq | -n Note] [-u Note] [-v] [filename]\n");
  123.       return 1;
  124.     }
  125.  
  126.   /* check out the putative RIFF WAVE on stdin */
  127.  
  128.   if (read(infd, thing, 12)<=0)
  129.     {
  130.       perror("wav2pat: I can't read your WAVE");
  131.       return 3;
  132.     }
  133.  
  134.   if (memcmp(thing, "RIFF", 4) || memcmp(thing+8, "WAVE", 4))
  135.     {
  136.       fprintf(stderr, "wav2pat: I want a RIFF WAVE on stdin!\n");
  137.       return 2;
  138.     }
  139.  
  140.   while (datasize==-1)
  141.     {
  142.       if (read(infd, thing, 8)!=8)
  143.     {
  144.       perror("wav2pat: "
  145.          "Your WAVE ran out before I got to the interesting bits");
  146.       return 3;
  147.     }
  148.       junklength=LE_LONG(*((int32 *)(thing+4)));
  149.  
  150.       /* This Microsoft file format is designed to be impossible to
  151.      parse correctly if one doesn't have the full specification.
  152.      If you have a wave with an INFO "chunk", you lose. Thank you
  153.      for playing. */
  154.  
  155.       if (!memcmp(thing, "fmt ", 4))
  156.     {
  157.       if (junklength > 4096)
  158.         {
  159.           fprintf(stderr, "wav2pat: "
  160.               "WAVEs with %ld-byte format blocks make me throw up!\n",
  161.               junklength);
  162.           return 2;
  163.         }
  164.       if (read(infd, thing, junklength) != junklength)
  165.         {
  166.           perror("wav2pat: Your WAVE is mangled");
  167.           return 3;
  168.         }
  169.       if (LE_SHORT(*((int16 *)(thing))) != 1)
  170.         {
  171.           fprintf(stderr, "wav2pat: I don't understand your WAVE. "
  172.               "It has a type %d format chunk!\n",
  173.               LE_SHORT(*((int16 *)(thing))));
  174.           return 2;
  175.         }
  176.       if (LE_SHORT(*((int16 *)(thing + 2))) != 1)
  177.         {
  178.           fprintf(stderr, "wav2pat: This WAVE has %d channels! " 
  179.               "There can be only one!\n",
  180.               LE_SHORT(*((int16 *)(thing + 2))));
  181.           return 2;
  182.         }
  183.       samplerate=LE_LONG(*((int32 *)(thing + 4)));
  184.       switch(LE_SHORT(*((int16 *)(thing + 14))))
  185.         {
  186.         case 8: modes |= MODES_UNSIGNED; break;
  187.         case 16: modes |= MODES_16BIT; break;
  188.         default:
  189.           fprintf(stderr, "wav2pat: Ack! Ppthbth! %d-bit samples!",
  190.               LE_SHORT(*((int16 *)(thing + 14))));
  191.           return 2;
  192.         }
  193.       if (verbosity)
  194.         fprintf(stderr, "wav2pat: This is a %d-bit, %ld Hz WAVE\n",
  195.             (LE_SHORT(*((int16 *)(thing + 14)))),
  196.             samplerate);
  197.     }
  198.       else if (!memcmp(thing, "data", 4))
  199.     {
  200.       if (samplerate==-1)
  201.         {
  202.           fprintf(stderr, "wav2pat: Your WAVE has no format information before data!\n");
  203.           return 2;
  204.         }
  205.       if (verbosity)
  206.         fprintf(stderr, "wav2pat: It has %ld bytes of data\n", junklength);
  207.       datasize=junklength;
  208.     }
  209.       else
  210.     {
  211.       if (verbosity)
  212.         fprintf(stderr, "wav2pat: "
  213.             "Your WAVE has a %ld-byte chunk called `%4.4s'\n",
  214.             junklength, thing);
  215.  
  216.       /* It's cool to pad chunks with NULs to align them on
  217.              half-word boundaries. */
  218.       if (junklength & 1)
  219.         junklength++;
  220.  
  221.       while (junklength>0)
  222.         {
  223.           if ((c=read(infd, thing, (junklength>4096) ? 4096 : junklength)) 
  224.           <= 0)
  225.         {
  226.           perror("wav2pat: Now your WAVE has run out of data");
  227.           return 3;
  228.         }
  229.           junklength -= c;
  230.         }
  231.     }
  232.     }
  233.  
  234.   /* hammer together something that looks like a GUS patch header */
  235.  
  236. #define pound(a) *point++=(a);
  237. #define pounds(a) { *((int16 *)point)=LE_SHORT(a); point+=2; }
  238. #define poundl(a) { *((int32 *)point)=LE_LONG(a); point+=4; }
  239. #define bounce(a) point += a;
  240.   
  241.   memset(thing, 0, 335);
  242.   point=thing;
  243.  
  244.   /* header */
  245.   memcpy(point, "GF1PATCH110", 12);
  246.   point += 12;
  247.  
  248.   /* Gravis ID */
  249.   memcpy(point, "ID#000002", 10);
  250.   point += 10;
  251.   
  252.   /* description */
  253.   strcpy(point, "Copyleft 1995 EWE&U Conductions and one Retreated Gravi\032");
  254.   point += 60;
  255.  
  256.   pound(1); /* instruments */
  257.   pound(14); /* voices */
  258.   pound(0); /* channels */
  259.   pounds(1); /* waveforms */
  260.   pounds(127); /* master volume */
  261.   poundl(datasize); /* data size */
  262.   bounce(36); /* reserved */
  263.  
  264.   pounds(1); /* instrument # */
  265.   strcpy(point, "Bleahnoise"); /* instrument name */
  266.   point += 16;
  267.   poundl(datasize); /* instrument size */
  268.   pound(1); /* layers */
  269.   bounce(40); /* reserved */
  270.  
  271.   pound(0); /* layer duplicate */
  272.   pound(0); /* layer */
  273.   poundl(datasize); /* layer size */
  274.   pound(1); /* samples */
  275.   bounce(40); /* reserved */
  276.   
  277.   strcpy(point, "bleah"); /* wave name */
  278.   point += 7;
  279.   pound(0); /* fractions */
  280.   poundl(datasize); /* wave size */
  281.   poundl(0); /* loop start */
  282.   poundl(datasize); /* loop end */
  283.   pounds(samplerate); /* sample rate */
  284.   poundl(8176); /* low freq */
  285.   poundl(12543854); /* high freq */
  286.   poundl(root); /* root freq */
  287.   pounds(512); /* tune */
  288.   pound(7);  /* balance */
  289.  
  290.   pound(63); /* envelope rates */
  291.   pound(63);
  292.   pound(63);
  293.   pound(63);
  294.   pound(63);
  295.   pound(63);
  296.  
  297.   pound(240); /* envelope offsets */
  298.   pound(240);
  299.   pound(240);
  300.   pound(240);
  301.   pound(240);
  302.   pound(240);
  303.  
  304.   pound(0); /* tremolo sweep */
  305.   pound(0); /* tremolo rate */
  306.   pound(0); /* tremolo depth */
  307.   pound(0); /* vibrato sweep */
  308.   pound(0); /* vibrato rate */
  309.   pound(0); /* vibrato depth */
  310.  
  311.   pound(modes); /* modes */
  312.  
  313.   pounds(note); /* scale freq */
  314.   pounds(1024); /* scale factor */
  315.   bounce(36); /* reserved */
  316.  
  317.   write(STDOUT_FILENO, thing, 335);
  318.  
  319.   /* wave data */
  320.  
  321.   while (datasize>0)
  322.     {
  323.       if ((c=read(infd, thing, (datasize>4096) ? 4096 : datasize)) 
  324.       <= 0)
  325.     {
  326.       perror("wav2pat: I can't read data");
  327.       return 3;
  328.     }
  329.       write(STDOUT_FILENO, thing, c);
  330.       datasize -= c;
  331.     }
  332.  
  333.   /* be courteous */
  334.   if (infd != STDIN_FILENO)
  335.     close(infd);
  336.  
  337.   return 0;
  338. }
  339.